#include "MyCam.h"

//-----------------------------------------------------------------------------
// Name: MyCam()
// Desc: Initillizes the camera setting position look at and up vectors
//		 it also sets the pitch and yaw angle as wells as near and far clipping
//		 distances
//-----------------------------------------------------------------------------
MyCam::MyCam(void)
{
	vPosition = D3DXVECTOR3(0.0f,0.0f,0.0f);		//Set position to 0,0,0
	vLookat = D3DXVECTOR3(0.0f,0.0f,1.0f);			//Set look at to 0,0,1
	vUp = D3DXVECTOR3(0.0f,1.0f,0.0f);				//Set up to 0,1,0
	fYawAng = fPitchAng = 0;
	D3DXMatrixIdentity(&mView);
	fMoveScale = 20;
	fFarPlane = 1;
	fNearPlane = 0;
	bCamChanged = false;
}

//-----------------------------------------------------------------------------
// Name: ~MyCam()
// Desc: Destructor probably need to get rid of some memory i alocated here
//-----------------------------------------------------------------------------
MyCam::~MyCam(void)
{
}
D3DXMATRIX* MyCam::GetViewMatrix()
{
	return &mView;
}
D3DXMATRIX* MyCam::GetProjectionMatrix()
{
	return &mProj;
}

//-----------------------------------------------------------------------------
// Name: Update()
// Desc: Update the cameras position and rotation then recalculates the view matrix
//-----------------------------------------------------------------------------
void MyCam::Update()
{
	if(bCamChanged)
	{

    D3DXMATRIX mCameraRot;
    D3DXMatrixRotationYawPitchRoll(&mCameraRot,  fYawAng, fPitchAng, 0);		//creates a rotation matrix
	D3DXVECTOR3 vWorldUp, vWorldAhead;
    D3DXVECTOR3 vLocalUp = D3DXVECTOR3(0, 1, 0);
    D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0, 0, 1);
    D3DXVec3TransformCoord(&vWorldUp, &vLocalUp, &mCameraRot);				//transforms the up vector to the new rotation
    D3DXVec3TransformCoord(&vWorldAhead, &vLocalAhead, &mCameraRot);		//transforms forawrd vector to the new rotation
	D3DXVECTOR3 vPosDeltaWorld;

	D3DXVec3TransformCoord(&vPosDeltaWorld, &vPosDelta, &mCameraRot);		// transform the new movment vector to the rotaion

    vEye += vPosDeltaWorld;
    // Update the lookAt position based on the eye position 
    vLookat = vEye + vWorldAhead;
    // Update the view matrix
    D3DXMatrixLookAtLH(&mView, &vEye, &vLookat, &vWorldUp);

    D3DXMatrixInverse(&mWorld, NULL, &mView);

	bCamChanged = false;
	vPosDelta.x = vPosDelta.y = vPosDelta.z =0;
	}
}

void MyCam::SetPos(D3DXVECTOR3 *Pos)
{
	vPosition = *Pos;
	bCamChanged = true;
}

D3DXVECTOR3 MyCam::getPos(void) {
	return vEye;
}


void MyCam::MoveForward(float Dist)
{
	vPosDelta.z += Dist;
	bCamChanged = true;
}
void MyCam::MoveRight(float Dist)
{
	vPosDelta.x += Dist;
	bCamChanged = true;
}
void MyCam::MoveUp(float Dist)
{
	vPosDelta.y += Dist;
	bCamChanged = true;
}

void MyCam::Yaw(float Angle)
{
	fYawAng += Angle;
	bCamChanged = true;
}

void MyCam::Pitch(float Angle)
{
	fPitchAng += Angle;
	bCamChanged = true;
}
void MyCam::SetViewParams(D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt)
{
	// Check that the vectors are there
	if(pvEyePt == NULL || pvLookatPt == NULL)
		return;
	//Set the Eye and Look at Vectors
	vEye = *pvEyePt;
    vLookat = *pvLookatPt;
	// Calc the view matrix
    D3DXVECTOR3 vUp( 0,1,0 );
    D3DXMatrixLookAtLH( &mView, pvEyePt, pvLookatPt, &vUp );

    D3DXMATRIX mInvView;
    D3DXMatrixInverse( &mInvView, NULL, &mView );

    // The axis basis vectors and camera position are stored inside the 
    // position matrix in the 4 rows of the camera's world matrix.
    // To figure out the yaw/pitch of the camera, we just need the Z basis vector
    D3DXVECTOR3* pZBasis = (D3DXVECTOR3*)&mInvView._31;

    fYawAng = atan2f(pZBasis->x, pZBasis->z);
    float fLen = sqrtf(pZBasis->z * pZBasis->z + pZBasis->x * pZBasis->x);
    fPitchAng = -atan2f(pZBasis->y, fLen);
}
void MyCam::SetProjParams(float n_fFOV, float n_fAspect, float n_fNearPlane, float n_fFarPlane)
{
	fFOV = n_fFOV;
	fAspect = n_fAspect;
	fNearPlane = n_fNearPlane;
	fFarPlane = n_fFarPlane;

	D3DXMatrixPerspectiveFovLH(&mProj, fFOV, fAspect, fNearPlane, fFarPlane);
}

LRESULT MyCam::HandleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(hWnd);
	UNREFERENCED_PARAMETER(lParam);

	switch(uMsg)
	{
	case WM_KEYDOWN:
		{
			switch(wParam)
			{
			case 'W':
				MoveForward(fMoveScale);
				break;
			case 'A':
				MoveRight(-fMoveScale);
				break;
			case 'S':
				MoveForward(-fMoveScale);
				break;
			case 'D':
				MoveRight(fMoveScale);
				break;
			case 'Q':
				MoveUp(fMoveScale);
				break;
			case 'E':
				MoveUp(-fMoveScale);
				break;
			case 'U':
				Pitch(-0.1f);
				break;
			case 'J':
				Pitch(0.1f);
				break;
			case 'K':
				Yaw(0.1f);
				break;
			case 'H':
				Yaw(-0.1f);
				break;
			}
			break;
		}

/*	case WM_KEYUP:
		{
			switch(wParam)
			{
			case 'W':
				break;
			case 'A':
				break;
			case 'S':
				break;
			case 'D':
				break;
			case 'Q':
				break;
			case 'E':
				break;
			}
			break;
		}*/
	}
	return FALSE;
}